import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
} from "@nestjs/common";
import { FastifyRequest } from "fastify";
import { Observable, of } from "rxjs";
import { tap } from "rxjs/operators";
import { PrismaClient } from "@prisma/client";

import { WebResult } from "src/common/web.result";
import * as jwt from "jsonwebtoken";

@Injectable()
export class LoginInterceptor implements NestInterceptor {
  constructor(private readonly prisma: PrismaClient) {}

  intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Observable<any> | Promise<Observable<any>> {
    return new Promise(async (resolve) => {
      console.log("verifyToken");
      const now = Date.now();

      const request: FastifyRequest = context.switchToHttp().getRequest();
      const token: any = request.headers["token"];
      if (!token) {
        resolve(of(WebResult.failure(undefined, "token is null")));
        return;
      }

      const decodeToken = jwt.decode(token);
      if (!decodeToken) {
        resolve(of(WebResult.failure(undefined, "token is wrong")));
        return;
      }
      const uid = decodeToken["id"];
      const username = decodeToken["username"];
      if (!uid || !username) {
        resolve(of(WebResult.failure(undefined, "token is wrong")));
        return;
      }

      const user = await this.prisma.user.findUnique({
        select: {
          id: true,
          password: true,
        },
        where: {
          id: uid,
          username,
        },
      });
      if (!user) resolve(of(WebResult.failure(undefined, "不存在的用户")));

      jwt.verify(token, user.password, (err: any) => {
        if (err) {
          resolve(of(WebResult.failure(undefined, "权限不足")));
          return;
        }

        resolve(
          next
            .handle()
            .pipe(tap(() => console.log(`After... ${Date.now() - now}ms`))),
        );
      });
    });
  }
}
